home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 22 / Amiga Format AFCD22 (Jan 1998, Issue 106).iso / -seriously_amiga- / shareware / hardware / lcdaemon / programmer / guppy.c next >
C/C++ Source or Header  |  1997-11-05  |  8KB  |  290 lines

  1. /*    (Tab size 4)    */
  2.  
  3. /*    Grand Unified Parallel Port driver for LCDaemon    */
  4. #include <clib/exec_protos.h>
  5. #include <clib/misc_protos.h>
  6. #include <clib/expansion_protos.h>
  7. #include <devices/timer.h>
  8. #include <libraries/configvars.h>
  9. #include <hardware/cia.h>
  10. #include "lcd.h"
  11.  
  12. #include <resources/misc.h>    /*    Parallel port        */
  13. #include "mfc3bits.h"        /*    Multifacecard 3    */
  14. #include "pitbits.h"            /*    Multifacecard 2    */
  15.  
  16. /*
  17. ** Exported to main driver
  18. */
  19.  
  20. STRPTR    lcd_alloc(struct lcdparams *);
  21. void    lcd_free(void);
  22. void    lcd_delayfor(ULONG);
  23. void    lcd_putchar(UBYTE,BOOL,ULONG,ULONG);
  24.  
  25. /*
  26. ** Imported from driver
  27. */
  28.  
  29. extern STRPTR startup;    /*    If !=NULL , points to STARTUP parameter*/
  30. extern struct timerequest *timereq;
  31.  
  32. /*
  33. ** Implementation
  34. */
  35.  
  36. struct Library *MiscBase=NULL;
  37. extern struct CIA ciaa,ciab;
  38. static STRPTR lcdaemonparname= "LCDaemon parallel port driver";
  39.  
  40. static BOOL portopen=FALSE,bitsopen=FALSE;
  41. struct mfc3 *mfc3=NULL;
  42. struct pit *pit=NULL;
  43. UBYTE pitunit=1;
  44.  
  45. UBYTE kind=0;
  46.  
  47. /*    Allocate anything needed, optionally making use of *startup    */
  48. STRPTR lcd_alloc(struct lcdparams *param){
  49.     struct ConfigDev *device;
  50.  
  51.     if(!startup){    /*    Supply default    */
  52.         startup="";
  53.     }
  54.     /*    If supplied, try to use the first letter of the startup parameter to guide the choice which port to use    */
  55.     switch(*startup++){
  56.         default:
  57.             startup--;    /*    If unknown, just autodetect    and undo the ++ in the switch()    */
  58.  
  59.         case 'M':
  60.         case 'm':
  61.         /*    Check for Multifacecard 3    */
  62.         if(device=FindConfigDev(NULL,2092,18)){
  63.             mfc3=(struct mfc3 *)((ULONG)(device->cd_BoardAddr)+MFC3_PIA_OFFSET);
  64.             kind=1;
  65.             return("Multifacecard III");
  66.         }
  67.  
  68.         case 'L':
  69.         case 'l':
  70.         /*    Check for Multifacecard II    */
  71.         if((device=FindConfigDev(NULL,2092,16))||(device=FindConfigDev(NULL,2092,17))){
  72.             kind=2;
  73.             pit=(struct pit *)((ULONG)(device->cd_BoardAddr)+0x100);
  74.             pit->pit_pcdr&=~0x50;
  75.             pit->pit_pcddr|=0x50;
  76.             if(startup){
  77.                 switch(*startup){
  78.                     case '0':
  79.                         pitunit=0;
  80.                         break;
  81.                     default:
  82.                         pitunit=1;
  83.                 }
  84.             }else{
  85.                 pitunit=1;
  86.            }
  87.             return("Multifacecard II");
  88.         }
  89.  
  90.         case 'P':
  91.         case 'p':
  92.         /*    Fall back to parallel port    */
  93.         if(!(MiscBase=OpenResource("misc.resource"))) return(NULL);
  94.         if(!(portopen=(BOOL)!AllocMiscResource(MR_PARALLELPORT,lcdaemonparname))) return(NULL);
  95.         if(!(bitsopen=(BOOL)!AllocMiscResource(MR_PARALLELBITS,lcdaemonparname))) return(NULL);
  96.         ciaa.ciaprb=(UBYTE)0x00;
  97.         ciaa.ciaddrb=(UBYTE)0xff;        /*    Put data lines as output        */
  98.         ciab.ciapra&=~(UBYTE)0x07;
  99.         ciab.ciaddra|=(UBYTE)0x07;        /*    Put control lines as output        */
  100.         kind=3;
  101.         return("Parallel port");
  102.     }
  103. }
  104.  
  105. /*    Free anything allocated in lcd_alloc    */
  106. void lcd_free(void){
  107.  
  108.     /*    MFC2 : nothing to free    */
  109.  
  110.     /*    MFC3 : nothing to free    */
  111.  
  112.     /*    Amiga parallel port        */
  113.     if(bitsopen) FreeMiscResource(MR_PARALLELBITS);
  114.     if(portopen) FreeMiscResource(MR_PARALLELPORT);
  115. }
  116.  
  117. /****************************************************************************\
  118. **    AmigaDOS Delay(), but using microseconds                                **
  119. \****************************************************************************/
  120. void lcd_delayfor(ULONG micros){
  121.     timereq->tr_node.io_Command=TR_ADDREQUEST;
  122. //    if(micros>3000){
  123. //        FPuts(Output(),"??");Flush(Output());
  124. //        micros=1000;
  125. //    }
  126.     timereq->tr_time.tv_micro=micros%1000000;
  127.     timereq->tr_time.tv_secs=micros/1000000;
  128. //    FPuts(Output(),">");Flush(Output());
  129.     DoIO((struct IORequest *)timereq);
  130. //    FPuts(Output(),"<");Flush(Output());
  131. }
  132.  
  133. /****************************************************************************\
  134. **    Send code to LCD, with pause for LCD to comply                            **
  135. **                                                                                    **
  136. **    Hardware:                                                                        **
  137. **                                                                                    **
  138. **    Centronics                LCD                                                **
  139. **    D0...D7            ->        d0...d7                                            **
  140. **    BUSY                ->        Enable                                                **
  141. **    POUT                ->        Register Select                                    **
  142. **    SEL                ->        Enable 1                                            **
  143. **                                                                                    **
  144. \****************************************************************************/
  145. void lcd_putchar(UBYTE code,BOOL data,ULONG micros,ULONG ctrlmask){
  146. //    FPuts(Output(),"*");Flush(Output());
  147.     switch(kind){
  148.     case 1:
  149.         /*    MFC3 PIA:
  150.         BUSY    =    PA0
  151.         POUT    =    PA1
  152.         SEL    =    PA2
  153.         +5V(14)    =    PA6
  154.         DATA    =    PB
  155.         */
  156.  
  157.         Forbid();
  158.         mfc3->mfc_pacr=mfc3->mfc_pbcr=0x0;    /*    Address data direction register    */
  159.         mfc3->mfc_pb=0xff;                    /*    All data lines are outputs        */
  160.         mfc3->mfc_pa=0x47;                    /*    Pin 14, and POUT,BUSY,SEL: output    */
  161.         mfc3->mfc_pacr=mfc3->mfc_pbcr=0x04;    /*    Output register, no interrupts    */
  162.  
  163.         mfc3->mfc_pb=code;                        /*    Put code on data lines        */
  164.         mfc3->mfc_pa=0x40;                        /*    Disable BUSY and POUT        */
  165.         if(data){                                /*    Adjust Register Select        */
  166.             mfc3->mfc_pa|=0x02;
  167.         }
  168.         Permit();
  169.  
  170.         lcd_delayfor(1);
  171.         Forbid();
  172.         if(ctrlmask&1){
  173.             mfc3->mfc_pa|=0x01;                    /*    Assert E0 line                */
  174.         }
  175.         if(ctrlmask&2){
  176.             mfc3->mfc_pa|=0x04;                    /*    Assert E1 line                */
  177.         }
  178.         Permit();
  179.  
  180.         lcd_delayfor(1);
  181.  
  182.         Forbid();
  183.         mfc3->mfc_pa&=~0x05;                    /*    Disable E after 1000 ns        */
  184.         Permit();    
  185.  
  186.         lcd_delayfor(micros);                /*    Wait while LCD processes...        */
  187.  
  188.         break;
  189.     case 2:
  190.         if(pitunit){
  191.             /*    Code for pit.device 1    */
  192.             /* BUSY=PC6 POUT=PC4    */
  193.             Forbid();
  194.             pit->pit_pbddr=0xff;
  195.             pit->pit_pcddr|=0x52;                    /*    Damned pit.device ! Thief!    */
  196.             pit->pit_pbdr=code;                        /*    Put code on data lines        */
  197.             pit->pit_pcdr&=~0x52;                    /*    Disable SEL, BUSY and POUT        */
  198.             if(data){                                /*    Adjust Register Select        */
  199.                 pit->pit_pcdr|=0x10;
  200.             }
  201.             Permit();
  202.  
  203.             lcd_delayfor(1);
  204.  
  205.             Forbid();
  206.             pit->pit_pcddr|=0x52;                    /*    Damned pit.device ! Thief!    */
  207.             if(ctrlmask&1){
  208.                 pit->pit_pcdr|=0x40;                    /*    Assert E line of controller 1 (BUSY)    */
  209.             }
  210.             if(ctrlmask&2){
  211.                 pit->pit_pcdr|=0x02;                    /*    Assert E line of controller 3 (SEL)    */
  212.             }
  213.             Permit();
  214.  
  215.             lcd_delayfor(1);
  216.  
  217.             Forbid();
  218.             pit->pit_pcddr|=0x52;                    /*    Damned pit.device ! Thief!    */
  219.             pit->pit_pcdr&=~0x42;                    /*    Disable E after 1000 ns        */
  220.             Permit();    
  221.  
  222.             lcd_delayfor(micros);                /*    Wait while LCD processes...        */
  223.  
  224. //            pit->pit_pbddr=0x00;                /*    float D0-D7 again (saves power)    */
  225.         }else{
  226.             /*    Code for pit.device 0    */
  227.             /* E=BUSY=PC7 RS=POUT=PC2    */
  228.             Forbid();
  229.             pit->pit_paddr=0xff;
  230.             pit->pit_pcddr|=0x85;                    /*    Damned pit.device ! Thief!    */
  231.             pit->pit_padr=code;                        /*    Put code on data lines        */
  232.             pit->pit_pcdr&=~0x85;                    /*    Disable SEL, BUSY and POUT        */
  233.             if(data){                                /*    Adjust Register Select        */
  234.                 pit->pit_pcdr|=0x04;
  235.             }
  236.             Permit();
  237.  
  238.             lcd_delayfor(1);
  239.  
  240.             Forbid();
  241.             pit->pit_pcddr|=0x85;                    /*    Damned pit.device ! Thief!    */
  242.             if(ctrlmask&1){
  243.                 pit->pit_pcdr|=0x80;                    /*    Assert E line    (BUSY)    */
  244.             }
  245.             if(ctrlmask&2){
  246.                 pit->pit_pcdr|=0x01;                    /*    Assert E line    (SEL)    */
  247.             }
  248.             Permit();
  249.  
  250.             lcd_delayfor(1);
  251.  
  252.             Forbid();
  253.             pit->pit_pcddr|=0x85;                    /*    Damned pit.device ! Thief!    */
  254.             pit->pit_pcdr&=~0x81;                    /*    Disable E after 1000 ns        */
  255.             Permit();    
  256.  
  257.             lcd_delayfor(micros);                /*    Wait while LCD processes...        */
  258.  
  259.             pit->pit_paddr=0x00;                /*    float D0-D7 again (saves power)    */
  260.         }
  261.         break;
  262.     case 3:
  263.         ciaa.ciaddrb=0xff;                    /*    Parallel lines as output        */
  264.         ciaa.ciaprb=code;                    /*    Put code on parallel data lines    */
  265.         if(!data){
  266.             ciab.ciapra&=~((UBYTE)0x02);    /*    Data=0    ->    RS=1                */
  267.         } else {
  268.             ciab.ciapra|=(UBYTE)0x02;        /*    Data=1    ->    RS=1                */
  269.         }
  270.         lcd_delayfor(1);
  271.  
  272.         if(ctrlmask&1){
  273.             ciab.ciapra|=(UBYTE)0x01;            /*    Assert E line    (BUSY)                */
  274.         }
  275.         if(ctrlmask&2){
  276.             ciab.ciapra|=(UBYTE)0x04;            /*    Assert E line    (SEL)                */
  277.         }
  278.  
  279.         lcd_delayfor(1);
  280.  
  281.         ciab.ciapra&=~((UBYTE)0x05);        /*    Disable E after 1000 ns            */
  282.     
  283.         lcd_delayfor(micros);                /*    Wait while LCD processes...        */
  284.  
  285.         /*    ciaa.ciaddrb=0x00;*/                    /*    float D0-D7 again (saves power)    */
  286.     default:
  287.     }
  288. }
  289.  
  290.